/*
条件类型
1. 三元表达式，如泛型， 只要满足就可以，属性可多不可少
A extends B ? C : D 

2. 条件分发
依次取出联合类型中的每一项去匹配，最后生成一个新的联合类型， 只有联合类型才有
never 在联合类型中可以被忽略
3. 内置类型（条件分发的应用）
-- Exclude<T, U> ,将 u 从联合类型 T 中排除
-- Extract<T,U>  ，抽离类型,J两 U 从 联合类型 T 中抽离出来, 排除其他
-- NonNullable<T> , 将 联合类型中的 null 或 undefined 清理掉

4. 内置类型, 类型推导
-- ReturnType 与 infer一起使用, 推导出函数的返回值类型 , infer R 推导出 R 的类型, 不调用函数得到其返回的类型，只支持函数
-- Parameters 与 infer 一起使用，推导出函数的参数类型
-- ConstructorParameters 与 infer 一起使用，获取构造函数的参数类型,本质是个数组
-- InstanceType 与 infer 一起使用， 获取类的实例的类型
*/

interface Bird {
    fly: string
}
interface Sky {
    sky: string
}

interface Fish {
    swimming: string
}
interface Water {
    water: string
}

type MyType<T> = T extends Bird ? Sky : Water // 泛型约束，具有 Bird 的属性即可,可多不可少
type X = MyType<Bird> // x 为 Sky

type animal = {
    fly: 'sky',
    swimming: 'swimming'
}
type M = MyType<animal> // M 为 Sky

//-------------条件分发-----------------------------
type MM = MyType<Bird | Fish> // MM 为 Sky | Water 的联合类型


//-----------------条件分发的使用场景-----------------------------

// T 是一个联合类型，依次将 T 中的每一个类型拿出来换和 U 比较, 满足就是never, 否则就是自身，最后实现将 U 从 T 中排除的目的；
// ----------内置类型 Exclude---------------
type Exclude<T, U> = T extends U ? never : T

type xxx = number | boolean | never // 可将 never 删除，即忽略，等同于 number | boolean

// 将 boolean 从联合类型中排除
type xx = Exclude<string | number | boolean, boolean>

//--------------内置类型Extract------------------------------
// 将 boolean 从联合类型中提取出来，排除其他
type Extract<T, U> = T extends U ? T : never
type yyy = never | never | boolean  // 可将 never 删除，即忽略，等同于 boolean
type yy = Extract<string | number | boolean, boolean>

//----------------内置类型 NonNullable ， 非 null 或 undefined 检测---------------------
type NonNullable<T> = T extends null | undefined ? never : T  // 将 null 或 undefined 干掉
type tt = NonNullable<string | number | null>    // string | number

//----------------类型推导：ReturnType 和 infer------------------------------
// 只支持函数
function getUser(a: string, b: number) {
    return { name: 'zs', age: 12 }
}

// 从函数推导出其返回值 XX 的类型
type ReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer XX ? XX : never
type NyRetuenType = ReturnType<typeof getUser>  // 不调用函数，得到其返回的类型

// 推导出函数的参数类型
type Prameters<T extends (...args: any[]) => any> = T extends (...args: infer pp) => any ? pp : any
type MyPrameters = Prameters<typeof getUser>  //  推导出函数的参数类型

// 获取构造函数得参数类型, 是一个数组
class Animal {
    constructor(a: number, b: string) { }
}

// 获取构造函数的参数类型
type ConstructorParameters<T extends { new(...args: any[]): any }> = T extends { new(...args: infer aaa): any } ? aaa : never
type MyConstructorParameters = ConstructorParameters<typeof Animal>

//获取类的实例的类型
type InstanceType<T extends { new(...args: any[]): any }> = T extends { new(...args: any[]): infer rrr } ? rrr : never
type MyInstanceType = InstanceType<typeof Animal> // 等同于 type MyInstanceType = Animal
export { }